<template>
	<template v-if="$store.chart.getTargetData.orgConfig.filter">
		<n-card>
			<p><span class="func-keyword">function</span>&nbsp;&nbsp;filter(data, res)&nbsp;&nbsp;{</p>
			<!-- 函数体 -->
			<div class="go-ml-4">
				<n-code :code="$store.chart.getTargetData.orgConfig.filter" language="typescript"></n-code>
			</div>
			<p>}</p>
			<template #footer>
				<n-space justify="end">
					<n-button type="primary" tertiary size="small" @click="addFilter">
						<template #icon>
							<n-icon>
								<filter-edit />
							</n-icon>
						</template>
						编辑
					</n-button>
					<n-button tertiary size="small" @click="delFilter"> 删除 </n-button>
				</n-space>
			</template>
		</n-card>
	</template>
	<template v-else>
		<n-button class="go-ml-3" @click="addFilter">
			<template #icon>
				<n-icon>
					<filter-edit />
				</n-icon>
			</template>
			新增过滤器
		</n-button>
	</template>

	<!-- 弹窗 -->
	<n-modal class="my-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false" :closeOnEsc="false">
		<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 600px">
			<template #header>
				<n-space>
					<n-text>过滤器函数编辑器</n-text>
				</n-space>
			</template>
			<template #header-extra> </template>
			<n-space size="small" vertical>
				<n-space justify="space-between">
					<div>
						<n-space vertical>
							<n-tag type="info">
								<span class="func-keyword">function</span>&nbsp;&nbsp;{{
									requestDataType == 2 ? 'filter(data)' : 'filter(data, res)'
								}}&nbsp;&nbsp;{
							</n-tag>
							<my-monaco-editor v-model:modelValue="filter" width="460px" height="380px" language="javascript" />
							<n-tag type="info">}</n-tag>
						</n-space>
					</div>
					<n-divider vertical style="height: 480px" />
					<n-scrollbar style="max-height: 480px">
						<n-space :size="15" vertical>
							<div class="editor-data-show">
								<n-space>
									<n-text depth="3">默认过滤数据(data)：</n-text>
									<n-code :code="toString(sourceData?.data) || '暂无'" language="json" :word-wrap="true"></n-code>
								</n-space>
							</div>
							<div class="editor-data-show">
								<n-space>
									<n-text depth="3">接口返回数据(res)：</n-text>
									<n-code :code="toString(sourceData) || '暂无'" language="json" :word-wrap="true"></n-code>
								</n-space>
							</div>
							<div class="editor-data-show">
								<n-space>
									<n-text depth="3">过滤器结果：</n-text>
									<n-code :code="filterRes || '暂无'" language="json" :word-wrap="true"></n-code>
								</n-space>
							</div>
						</n-space>
					</n-scrollbar>
				</n-space>
			</n-space>
			<template #action>
				<n-space justify="space-between">
					<div class="flex s-center">
						<n-tag :bordered="false" type="primary">
							<template #icon>
								<my-icon icon="DocumentText" />
							</template>
							规则
						</n-tag>
						<n-text class="m-l-10" depth="2">过滤器默认处理接口返回值的「data」字段</n-text>
					</div>
					<n-space>
						<n-button size="medium" @click="closeFilter">取消</n-button>
						<n-button size="medium" type="primary" @click="saveFilter">保存</n-button>
					</n-space>
				</n-space>
			</template>
		</n-card>
	</n-modal>
</template>

<script setup>
import { toString, GetProperty } from '@/utils';
import { resultArrange, resultOutApi } from '@a/data';

// 受控弹窗
const showModal = ref(false);
// filter 函数模板
const filter = ref($store.chart.getTargetData.orgConfig.filter || `return data`);
// 过滤错误标识
const errorFlag = ref(false);
// 目标静态/接口数据
const sourceData = ref('');

// 动态获取数据
const { reqID, requestDataType, requestData } = toRefs($store.chart.getTargetData.orgConfig.request);

const fetchTargetData = async () => {
	try {
		// 从Store获取当前请求接口ID
		if (requestDataType.value == 1 && !reqID.value) return msgWarning('未选择接口，请检查！');

		if (requestDataType.value == 1 && reqID.value) {
			const res = await resultArrange({ id: reqID.value });
			if (res) {
				sourceData.value = res;
				return;
			}
			msgWarning('没有拿到返回值，请检查接口！');
		}

		if (requestDataType.value == 2 && !requestData.value) return msgWarning('无数据绑定，请检查！');

		if (requestDataType.value == 2 && requestData.value) {
			sourceData.value = GetProperty($store.chart.pageData, requestData.value);
		}

		if (requestDataType.value == 3 && reqID.value) {
			const res = await resultOutApi({ id: reqID.value });
			if (res) {
				sourceData.value = res;
				return;
			}
			msgWarning('没有拿到返回值，请检查接口！');
		}
	} catch (error) {
		console.error(error);
		msgWarning('数据异常，请检查参数！');
	}
};

// 过滤结果
const filterRes = computed(() => {
	try {
		// new Function() 可以接n个参数，最后一个参数作为函数体。
		if (requestDataType.value == 2) {
			const fn = new Function('data', filter.value);
			const response = cloneDeep(sourceData.value);
			const res = fn(response);
			errorFlag.value = false;
			return toString(res);
		} else {
			const fn = new Function('data', 'res', filter.value);
			const response = cloneDeep(sourceData.value);
			const res = fn(response?.data, response);
			errorFlag.value = false;
			return toString(res);
		}
	} catch (error) {
		errorFlag.value = true;
		return `过滤函数错误，日志：${error}`;
	}
});

// 新增过滤器
const addFilter = () => {
	showModal.value = true;
};

// 删除过滤器
const delFilter = () => {
	confirm('是否删除过滤器').then(() => {
		$store.chart.getTargetData.orgConfig.filter = undefined;
	});
};

// 关闭过滤器
const closeFilter = () => {
	showModal.value = false;
};

// 新增过滤器
const saveFilter = () => {
	if (errorFlag.value) {
		msgError('过滤函数错误，无法进行保存');
		return;
	}
	const { getTargetData } = $store.chart;
	getTargetData.orgConfig.filter = filter.value;
	if (filterRes.value) getTargetData.orgConfig.config.data = JSON.parse(filterRes.value);
	closeFilter();
};

watch(
	() => showModal.value,
	(newData) => {
		if (newData) {
			fetchTargetData();
			filter.value = $store.chart.getTargetData.orgConfig.filter || `return data`;
		}
	}
);
</script>

<style lang="scss" scoped>
.func-keyword {
	color: #b478cf;
}
@include b('chart-data-monaco-editor') {
	&.n-card.n-modal,
	.n-card {
		// @extend .go-background-filter;
	}
	.editor-data-show {
		width: 420px;
		padding: 20px;
		border-radius: 5px;
	}
}
</style>
